package cn.com.csg.smartenergy.modules.biz.task.core;

import cn.com.csg.smartenergy.common.Constant;
import cn.com.csg.smartenergy.common.DateUtils;
import cn.com.csg.smartenergy.mqtt.DeviceMqttOnlineClient;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @program: simple-demo
 * @description:
 * @author: WJJ
 * @date: 2022/5/05
 **/
@Component("sendTask")
@Slf4j
public class SendTask {
    @Autowired
    private DeviceMqttOnlineClient client;
    //"csg/terminal/dataReport/CSG300222/CSG/T20/KD-221T/20200728test"
    private String sendMessageTopic ="terminal/dataReport";
    //csg/notify/event/gwTerminal/status/CSG300222/CSG/T20/KD-221T/mqtt/20200728test
    private String onlineTopic ="notify/event/gwTerminal/status";
    /**
     * 发送消息
    manufacturer_id: "CSG300222"
    manufacturer_name: "CSG"
    device_type: "T20"
    model : "KD-221T"
    node_id : "20200728test"
     **/
    public void sendMessage(String serviceId,String manufacturerId, String manufacturerName, String deviceType, String model, String nodeId,String message,String jobId,ConcurrentHashMap<String,HashMap<String,Float>> SOC){
//        System.out.println(nodeId+"定时模拟数据: " + LocalDateTime.now());
        //"csg/terminal/dataReport/CSG300222/CSG/T20/KD-221T/20200728test"
        String topic = Constant.APP_NAME+Constant.FORWARD_SLASH
                + sendMessageTopic + Constant.FORWARD_SLASH
                + manufacturerId + Constant.FORWARD_SLASH
                + manufacturerName + Constant.FORWARD_SLASH
                + deviceType + Constant.FORWARD_SLASH
                + model + Constant.FORWARD_SLASH
                + nodeId;
        try {
            //=========================发送消息==============================================================
            HashMap data = new HashMap<String, Object>();
            String date = DateUtils.format(new Date(System.currentTimeMillis()), DateUtils.DATE_TIME_PATTERN);
            data.put(Constant.MSG_TIMESTAMP, date);
            //TODO:TOKEN??
            data.put(Constant.MSG_TOKEN, "9c0ca881-eac8-463e-8989-db0059fe3ded");
            HashMap body = new HashMap<String, Object>();
            body.put(Constant.MSG_SERVICE_ID, serviceId);
            Map serviceProperties = getMessageData(jobId,message,SOC);
            body.put(Constant.MSG_SERVICE_PROPS,serviceProperties);
            data.put(Constant.MSG_BODY, body);
            message = JSON.toJSONString(data);
            //=======================================================================================
            MqttMessage mqttMessage = new MqttMessage(message.getBytes());
            client.publish(topic, mqttMessage);
            log.info(LocalDateTime.now() +"："+nodeId+"：定时任务模拟数据发送消息成功test:{}",message);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    /**
     * 模版转换获取消息体
     {
        "ALIV_B2C_BMS":
        {
            "default": 5,
            "enable": 1,
            "min": 0,
            "max": 100,
            "enum_enable": 1,
            "enum": ["1", "2"],
            "dataType": "int"
        },
        "BMS_Charge_Energe":
        {
            "default": 107.7,
            "enable": 1,
            "min": 0,
            "max": 100,
            "enum_enable": 0
         },
     "BMS_Current":
     {
     "default": 0,
     "enable": 1,
     "min": 0,
     "max": 100,
     "enum_enable": 0
     }
     }
     * @param body
     * @return
     */
    public Map<String, Object> getMessageData(String jobId, String body,ConcurrentHashMap<String,HashMap<String,Float>> SOC){
        HashMap<String, Object> bodyBody = new HashMap<>();
        Map<String, Object> data = JSONObject.parseObject(body,HashMap.class);
        data.forEach((key, value) -> {
//            System.out.println(key + ":" + value);
            Map<String, Object> item = (Map)value;
            String dataType = (String)item.get("dataType");
            Object ValueInfo = item.get("default");
            if((Integer)item.get("enable")==1) {
                /**
                 * soc在给定范围递增或递减，
                 * 到最大值时再递减，到最小值时再递增
                 */
                if(key.toUpperCase().contains("SOC")){
                    HashMap<String, Float> socItem = SOC.get(jobId);
                    if(socItem==null){
                        socItem = new HashMap<>();
                        socItem.put(key+Constant.UNDER_LINE+"trend",Float.valueOf(item.get("trend").toString()));
                        socItem.put(key+Constant.UNDER_LINE+"size",Float.valueOf(item.get("size").toString()));
                        socItem.put(key+Constant.UNDER_LINE+"max",Float.valueOf(item.get("max").toString()));
                        socItem.put(key+Constant.UNDER_LINE+"min",Float.valueOf(item.get("min").toString()));
                        if(Float.valueOf(item.get("trend").toString())==1){
                            socItem.put(key+Constant.UNDER_LINE+"soc",Float.valueOf(item.get("min").toString()));
                            ValueInfo = new BigDecimal(item.get("min").toString()).setScale(3, BigDecimal.ROUND_UP);
                        }else{
                            socItem.put(key+Constant.UNDER_LINE+"soc",Float.valueOf(item.get("max").toString()));
                            ValueInfo = new BigDecimal(item.get("max").toString()).setScale(3, BigDecimal.ROUND_UP);
                        }
                        SOC.put(jobId, socItem);
                    }else{
                        Float trend = socItem.get(key+Constant.UNDER_LINE+"trend");
                        Float size = socItem.get(key+Constant.UNDER_LINE+"size");
                        Float max = socItem.get(key+Constant.UNDER_LINE+"max");
                        Float min = socItem.get(key+Constant.UNDER_LINE+"min");
                        Float soc = socItem.get(key+Constant.UNDER_LINE+"soc");
                        if(trend==1){
                            soc += size ;
                            if(soc>=max){
                                trend = (float) -1;
                                socItem.put(key+Constant.UNDER_LINE+"trend",trend);
                                socItem.put(key+Constant.UNDER_LINE+"soc",socItem.get("max"));
                            }
                        }else{
                            soc -= size;
                            if(soc<=min){
                                trend = (float) 1;
                                socItem.put(key+Constant.UNDER_LINE+"trend",trend);
                                socItem.put(key+Constant.UNDER_LINE+"soc",socItem.get("min"));
                            }
                        }
                        socItem.put(key+Constant.UNDER_LINE+"soc",soc);
                        ValueInfo = new BigDecimal(soc).setScale(3, BigDecimal.ROUND_UP);
                    }

                }else{
                    /**
                     * 启用枚举值，则随机使用枚举值模拟
                     */
                    if((Integer)item.get("enum_enable")!=0&&(List<Integer>)item.get("enum")!=null){
                        Random random = new Random();
                        int random_ = random.nextInt(((List<Integer>) item.get("enum")).size());
                        ValueInfo = ((List<Integer>) item.get("enum")).get(random_);
                    }else{
                        if("int".equals(dataType)){
                            int min = Integer.valueOf(item.get("min").toString());
                            int max = Integer.valueOf(item.get("max").toString());
                            Random random = new Random();
                            ValueInfo = random.nextInt(max-min+1)+min;
                        }else if("decimal".equals(dataType)){
                            Float min = Float.valueOf(item.get("min").toString());
                            Float max = Float.valueOf(item.get("max").toString());
                            ValueInfo = random(min, max,3);
                        }
                    }
                }

            }
            bodyBody.put(key, ValueInfo);
        });
        return bodyBody;
    }

    /**
     * 生成指定范围，指定小数位数的随机数
     * @param max 最大值
     * @param min 最小值
     * @param scale 小数位数
     * @return
     */
    static BigDecimal random(float max, float min, int scale){
        scale = scale < 0 ? 0 : scale;
        if (max < min){
            float temp = max;
            max=min;
            min=temp;
        }
        BigDecimal cha = new BigDecimal(Math.random() * (max-min) + min);
        return cha.setScale(scale, BigDecimal.ROUND_UP);//保留 scale 位小数，并四舍五入
    }

    /**
     * 上线心跳
     manufacturer_id: "CSG300222"
     manufacturer_name: "CSG"
     device_type: "T20"
     model : "KD-221T"
     node_id : "20200728test"
     **/
    public void onLine(String manufacturerId, String manufacturerName, String deviceType, String model, String nodeId,String protocolType,String message) {
//        System.out.println(nodeId+"心跳连接: " + LocalDateTime.now());
        //csg/notify/event/gwTerminal/status/CSG300222/CSG/T20/KD-221T/mqtt/20200728test
        String topic = Constant.APP_NAME+Constant.FORWARD_SLASH
                + onlineTopic + Constant.FORWARD_SLASH
                + manufacturerId + Constant.FORWARD_SLASH
                + manufacturerName + Constant.FORWARD_SLASH
                + deviceType + Constant.FORWARD_SLASH
                + model + Constant.FORWARD_SLASH
                + protocolType.toLowerCase() + Constant.FORWARD_SLASH
                + nodeId;
        try {
            MqttMessage mqttMessage = new MqttMessage(message.getBytes());
            client.publish(topic, mqttMessage);
            log.info(LocalDateTime.now()+"："+nodeId+"：心跳连接:{}", message);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
    }

    public void taskWithParams(String param1, Integer param2) {
        System.out.println("这是有参示例任务sendtask：" + param1 + param2);
    }


}
